<template>
   	<div>
		<el-button-group> 
			<el-button :icon="MagicStick" @click="showSQLToColumnsDialog">根据SQL生成数据列</el-button>
			<el-button :icon="Download" type="info" @click="handleExportToJson">导出到JSON</el-button>
			<el-button :icon="Upload" @click="handleImportFromJson">导入JSON</el-button>
		</el-button-group>		
		<p />
	</div> 
	<div>
		<el-table :data="tableColumns" :key="'tablec'+key"
							style="width:100%"
							:cell-style="{padding:'3px 0'}" 
							height="500" 
							border 
							row-key="columnId" 
							ref="singleTable" 
							stripe
							>
			<el-table-column 
					type="index" 
					width="42" 
					fixed="left">
			</el-table-column>
			<el-table-column width="160" prop="columnId || Date.now()">
				<template #default="scope">
					<span v-if="scope.row.headerFlag">{{getHeaderSpace(scope.row)}}</span>
					<span v-else>数据列</span>
				</template>
			</el-table-column>
			<el-table-column label="" width="30">
				<i class="iconfont icon-drag drag-option column-drag-handler"><Rank style="width: 1em; height: 1em; margin-left: -4px;margin-right: 8px"/></i>
			</el-table-column>
			<!-- el-table-column label="columnId" prop="columnId" width="150" v-if=false></el-table-column -->
			<el-table-column 
				label="字段名称" 
				width="150" 
				prop="prop" 
				class-name="placeholder-hide">						
				<template #default="scope">
					<span v-if="scope.row.headerFlag">{{getHeaderTitle(scope.row)}}</span>
					<el-input v-else v-model="scope.row.prop"></el-input>
				</template>
			</el-table-column>
			<el-table-column label="显示名称" 
				width="150" prop="label">
				<template #default="scope">
					<el-input v-model="scope.row.label"></el-input>
				</template>
			</el-table-column>
			<el-table-column label="列宽(px/%)" 
				width="80" prop="width">
				<template #default="scope">
					<el-input v-if="!scope.row.headerFlag" v-model="scope.row.width"></el-input>
				</template>
			</el-table-column>
			<el-table-column label="是否显示" 
				width="65" prop="visible">
				<template #default="scope">
					<el-switch v-if="!scope.row.headerFlag" v-model="scope.row.visible"></el-switch>
				</template>
			</el-table-column>
			<el-table-column label="是否排序" 
				width="65" prop="sortable">
				<template #default="scope">
					<el-switch v-if="!scope.row.headerFlag"  v-model="scope.row.sortable"></el-switch>
				</template>
			</el-table-column>
			<!--
			<el-table-column label="后端排序" 
				width="90" prop="customSort">
				<template #default="scope">
					<el-switch v-if="!scope.row.headerFlag" v-model="scope.row.customSort"></el-switch>
				</template>
			</el-table-column>
			-->

			<el-table-column label="是否固定" 
				width="100" prop="fixed">
				<template #default="scope">
					<el-select v-if="!scope.row.headerFlag"  v-model="scope.row.fixed">
						<el-option key="false" value="">false</el-option>
						<el-option key="left" value="left">left</el-option>
						<el-option key="right" value="right">right</el-option>
					</el-select>
				</template>
			</el-table-column>
			<el-table-column label="对齐方式" 
				width="100" prop="align">
				<template #default="scope">
					<el-select v-model="scope.row.align">
							<el-option v-for="item in alignOptions" 
								:key="item.value" 
								:label="item.label" 
								:value="item.value">
							</el-option>
					</el-select>
				</template>
			</el-table-column>
			<el-table-column label="标题对齐方式" 
				width="100" prop="headerAlign">
				<template #default="scope">
					<el-select v-model="scope.row.headerAlign">
							<el-option v-for="item in alignOptions" 
								:key="item.value" 
								:label="item.label" 
								:value="item.value">
							</el-option>
					</el-select>
				</template>
			</el-table-column>
			<el-table-column label="拖拉宽度" 
				width="65" prop="resizable">
				<template #default="scope">
					<el-switch v-if="!scope.row.headerFlag" v-model="scope.row.resizable"></el-switch>
				</template>
			</el-table-column>
			<el-table-column label="检索字段" 
				width="65" prop="searchable">
				<template #default="scope">
					<el-switch v-if="!scope.row.headerFlag" v-model="scope.row.searchable"></el-switch>
				</template>
			</el-table-column>
			<el-table-column label="字段设置" 
				width="80" fixed="right" align="center">
				<template #default="scope">
					<el-button v-if="scope.row.searchable" :type="scope.row.fieldOptions ? 'primary' : ''" @click="showFieldOptionsDialog(scope.row)" size="small" plain round :icon="Edit"></el-button>
				</template>
			</el-table-column>				
			<el-table-column label="格式化函数" 
				width="80" fixed="right" align="center">
				<template #default="scope">
					<el-button :type="scope.row.formatterFn ? 'primary' : ''" @click="showRenderDialog(scope.row)" size="small" plain round :icon="Edit"></el-button>
				</template>
			</el-table-column>
			<el-table-column label="操作" 
				width="100" fixed="right" align="center">
				<template #default="scope">							
						<el-popover>
							<template #reference>
								<el-button title="增加列" size="small" circle type="primary" :icon="Plus"></el-button>
							</template>
							<el-menu class="opt-btn-menu"> 		
								<el-menu-item index="#" @click="handleAddColCommand('column', scope.$index,scope.row)">增加数据列</el-menu-item>
								<el-menu-item index="#" @click="handleAddColCommand('sub-column', scope.$index, scope.row)" :disabled="disableDropdownItem(scope.row, 'header')">插入下级数据列</el-menu-item>
								<el-menu-item index="#" @click="handleAddColCommand('header', scope.$index, scope.row)">插入表头</el-menu-item> 
								<el-menu-item index="#" @click="handleAddColCommand('sub-header', scope.$index, scope.row)" :disabled="disableDropdownItem(scope.row, 'sub-header')">插入下级表头</el-menu-item>  	 								
							</el-menu>

						</el-popover>		
					
					
					<el-button title="删除列" size="small" circle type="danger"
						@click="handleDelete(scope.$index, scope.row)" :icon="Delete"></el-button>
				</template>
			</el-table-column>
		</el-table>       
    </div>
	<div v-if="showRenderDialogFlag" v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']">
		<el-dialog title="格式化函数" 
							v-model="showRenderDialogFlag"
								:show-close="true" 
								class="drag-dialog small-padding-dialog" 
								append-to-body
								:close-on-click-modal="false" 
								:close-on-press-escape="false" 
								:destroy-on-close="true">
			<el-alert type="info" :closable="false" title="function formatter(row, column, cellValue, index){"></el-alert>
			<el-input
				v-model="formatterCode"
				:rows="6"
				type="textarea"
				placeholder="const [year, month, day] = cellValue.split('-');
return `${year}年${month}月${day}日`;"
			/>
			<el-alert type="info" :closable="false" title="}"></el-alert><p />
			<div slot="footer" class="dialog-footer">
				<el-button size="default" type="primary" @click="saveColumnRender">确定</el-button>
				<el-button size="default" @click="showRenderDialogFlag = false">取消</el-button>
			</div>
		</el-dialog>
	</div>
	<div v-if="showFieldOptionsDialogFlag" v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']">
		<el-dialog title="字段设置" 
							v-model="showFieldOptionsDialogFlag"
								:show-close="true" 
								class="drag-dialog small-padding-dialog" 
								append-to-body
								:close-on-click-modal="false" 
								:close-on-press-escape="false" 
								:destroy-on-close="true">
			<el-form label-width="auto" >
				<el-form-item label="字段类型" title="用于生成Search表单">				
					<el-select  v-model="fieldOptions.type" placeholder="请选择">
							<el-option v-for="item in fieldTypeOptions" :key="item.value" :label="item.label" :value="item.value">
							</el-option>
					</el-select>
				</el-form-item>
				<el-form-item label="字段格式">
					<el-select v-if="fieldOptions.type==='date'" v-model="fieldOptions.format" clearable>								
						<el-option-group
								v-for="group in fieldFormatOptions"
								:key="group.label"
								:label="group.label">
								<el-option
								v-for="item in group.options"
								:key="item.value"
								:label="item.label"
								:value="item.value">
								</el-option>
						</el-option-group>
					</el-select>
				</el-form-item>
				<el-form-item label="字段选项值">
					<SearchSelectOptionsInput  v-if="fieldOptions.type==='select' || fieldOptions.type==='multiselect'" v-model:options="fieldOptions.options"/>
				</el-form-item>
			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button size="default" type="primary" @click="saveFieldOptions">确定</el-button>
				<el-button size="default" @click="showFieldOptionsDialogFlag = false">取消</el-button>
			</div>
		</el-dialog>
	</div>
	<div v-if="showSQLToColumnDialogFlag" v-drag="['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header']">
		<el-dialog title="SQL语句生成数据列及测试数据" 
							v-model="showSQLToColumnDialogFlag"
								:show-close="true" 
								class="drag-dialog small-padding-dialog" 
								append-to-body
								:close-on-click-modal="false" 
								:close-on-press-escape="false" 
								:destroy-on-close="true">
			<el-alert type="info" :closable="false" title="支持mysql的create,update,insert语句"></el-alert>
			<el-input
				v-model="sqlString"
				:rows="6"
				type="textarea"
				placeholder=""
			/>
			<p />
			<!--
			<el-alert type="info" :closable="false" title="UPDATE `HC_DB`.`db_test` SET `NAME` = 'name_225' WHERE `ID` = 3;"></el-alert>
			<el-alert type="info" :closable="false" title="INSERT INTO `HC_DB`.`db_test` (`ID`, `NAME`) VALUES (3, 'name_225');"></el-alert>
			<el-alert type="info" :closable="false" title="CREATE TABLE `db_test`  (  `ID` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',  `NAME` varchar(50) CHARACTER SET gbk COLLATE gbk_chinese_ci NULL DEFAULT '' COMMENT '姓名',  PRIMARY KEY (`ID`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = gbk COLLATE = gbk_chinese_ci ROW_FORMAT = Compact;"></el-alert>	
			-->			
			<div slot="footer" class="dialog-footer">
				<el-button size="default" type="primary" @click="saveSQLToColumns">确定</el-button>
				<el-button size="default" @click="showSQLToColumnDialogFlag = false">取消</el-button>
			</div>
		</el-dialog>
	</div>
</template>

<script setup>
import { ref,onMounted, watch, nextTick } from 'vue'
import Sortable from "sortablejs"
import SearchSelectOptionsInput from "@/components/search-select-options-input.vue"
import {processSqlAndGenerateTestData, deepClone /* ,extractFieldsFromSql,generateTestData*/} from "@/utils/utils"
import {exportToJson} from "@/utils/export"
import { Plus, Delete, Edit, Rank, Download,Upload,MagicStick} from '@element-plus/icons-vue'
import {importFromJson} from "@/utils/import"

const props = defineProps({
	tableColumns: { 
		type: Array,
		default: () => [
			{ label: 'ID', value: 'id', type: 'number', align: 'left', width: '100px', sortable: true, editable: true, visible: true, options: [] },
			{ label: '姓名', value: 'name', type: 'text', align: 'left', width: '100px', sortable: true, editable: true, visible: true, options: [] },
		]
	},
	tableData: { type: Array, default: () => [] },
	key: { type: String, default: '' }
})
const emit = defineEmits(['update:tableColumns', 'update:tableData'])

const localTableColumns = ref(props.tableColumns)
const localTableData = ref(props.tableData)
	
const  alignOptions=ref([
	{
		value: 'left',
		label: 'left'
	}, {
		value: 'center',
		label: 'center'
	}, {
		value: 'right',
		label: 'right'
	},
])
const fieldTypeOptions= ref([
	{
		value: 'text',
		label: 'Text'
	}, {
		value: 'number',
		label: 'Number'
	}, {
		value: 'date',
		label: 'Date'
	}, {
		value: 'select',
		label: 'Select'
	}, {
		value: 'multiselect',
		label: 'multiSelect'
	},
])
const fieldFormatOptions = ref([{
		label: 'Date Format',
		options: [
			{value:'YYYY-MM-dd',label:"YYYY-MM-dd"},
			{value:'YYYY/MM/dd',label:"YYYY/MM/dd"},
			{value:'YYYY年MM月dd日',label:"YYYY年MM月dd日"},
			{value:'YYYY-MM-dd HH:mm:ss',label:"YYYY-MM-dd HH:mm:ss"},
			{value:'YYYY-MM-dd hh:mm:ss',label:"YYYY-MM-dd hh:mm:ss"},
		]
	}/*, {
		label: 'Number Format',
		options: [
			{value:'n1',label:"###,###,###,##0.######"},
			{value:'n2',label:"###,###,###,##0.00####"},
			{value:'n3',label:"###,###,###,##0.000000"},
			{value:'n4',label:"###,###,###,##0.000"},
			{value:'n5',label:"###,###,###,##0.00"},
			{value:'n6',label:"###,###,###,##0"},
			{value:'n7',label:"###,##0.00##%"},
		]
	}*/])
const singleTable = ref();
const tableColumnRows = ref([]);
const showRenderDialogFlag=ref(false)
const fieldOptions=ref({type:'',format:'',options:[]})
const showFieldOptionsDialogFlag=ref(false)
const showSQLToColumnDialogFlag=ref(false)
const sqlString=ref('')
const currentTableColumn = ref(null);
const sortable = ref();
const formatterCode = ref('');
	
const getHeaderSpace = (column) => {
	let level = getHeaderLevel(localTableColumns.value, column.columnId, 1);
	return "|" + "-".repeat(level > 6 ? 0 : 6 - level);
};
const getHeaderTitle = (column) => {
	let level = getHeaderLevel(localTableColumns.value, column.columnId, 1);
	return level + '级表头';
}

const getHeaderLevel = (columns, targetId, level) => {
	let found = false;
	columns.forEach(column => {
		if (column.columnId === targetId) {
			found = true;
		}
	});
	if (found) return level;

	let result = -1;
	columns.forEach(column => {
		if (column.children) {
			let childResult = getHeaderLevel(column.children, targetId, level + 1);
			if (childResult > -1) {
				result = childResult;
			}
		}
	});
	return result;
};
const handleAddColCommand = (actType, index, column) => {
	let row;

	if (actType === "column") {
		row = {
			columnId: Date.now(),
			show: false
		};
		insertTableColumnById(localTableColumns.value, column.columnId, row, false);
		//emit('update:columnsColumns', [...props.columns])
		//updateTableColumns();
	} else if (actType === "sub-column") {
		row = {
			columnId: Date.now(),
			show: false
		};
		insertTableColumnById(localTableColumns.value, column.columnId, row, true);
		//emit('update:localTableColumns', [...props.columns])
		//updateTableColumns();
	} else if (actType === "header") {
		row = {
			columnId: Date.now(),
			prop: "~",
			headerFlag: true,
			label: "header",
			align: "center",
			children: []
		};
		insertTableColumnById(localTableColumns.value, column.columnId, row, false);
		//emit('update:localTableColumns', [...props.columns])
		//updateTableColumns();
	} else if (actType === "sub-header") {
		row = {
			columnId: Date.now(),
			prop: "~",
			headerFlag: true,
			label: "header",
			align: "center",
			children: []
		};
		insertTableColumnById(localTableColumns.value, column.columnId, row, true);
		//emit('update:tableColumns', [...props.columns])
		//updateTableColumns();
	}

	
	nextTick(() => {
		singleTable.value.toggleRowExpansion(column, true);
	});
	};
const insertTableColumnById = (columnList, targetId, newColumn, isSubColumn) => {
	let targetIndex = -1;

	columnList.forEach((col, index) => {
		if (col.columnId === targetId) {
			targetIndex = index;
		}

		if (col.children) {
			insertTableColumnById(col.children, targetId, newColumn, isSubColumn);
		}
	});

	if (targetIndex > -1) {
		if (isSubColumn) {
			columnList[targetIndex].children.push(newColumn);
		} else {
			columnList.splice(targetIndex + 1, 0, newColumn);
		}
	}
};
const disableDropdownItem=(column, actType)=>{
			//console.log(!column.children, o)
	return !column.children
}
const handleDelete=(index,row)=>{
	if(localTableColumns.value.length === 1){
		console.error('删除列失败，当前列为唯一列')
		return false;
	}
	//console.log('handleDelete',index,row)
	deleteTableColumnById(localTableColumns.value, row.columnId)
	//updateTableColumns();
	//emit('update:tableColumns', [...props.columns])
}
const deleteTableColumnById = (columns, columnId) => {
	let targetIndex = -1;

	columns.forEach((col, index) => {
		if (col.columnId === columnId) {
			targetIndex = index;
		}

		if (col.children) {
			deleteTableColumnById(col.children, columnId);
		}
	});

	if (targetIndex > -1) {
		columns.splice(targetIndex, 1);
	}
};

const treeColumnsToArray = () => {
	const flatList = [];
	
	const traverse = (columns, level) => {
		columns.map(column => {
			let clonedColumn = deepClone(column);
			clonedColumn.nodeLevel = level;
			flatList.push(clonedColumn);
			
			if (column.children) {
				traverse(column.children, level + 1);
			}
		});
	};

	traverse(localTableColumns.value, 1);
	return flatList;
};
const getParentArrayOfTableColumn = (columns, targetId) => {
	let found = false;

	columns.forEach(column => {
		if (column.columnId === targetId) {
			found = true;
		}
	});

	if (found) return columns;

	let result = [];

	columns.forEach(column => {
		if (column.children) {
			let childResult = getParentArrayOfTableColumn(column.children, targetId);
			if (childResult.length > 0) {
				result = childResult;
			}
		}
	});

	return result;
};

		//表格拖动排序
const dragSort = () => {
	const tableBody = singleTable.value.$el.querySelectorAll(".el-table__body-wrapper .el-table__body > tbody")[0];
	sortable.value = Sortable.create(tableBody, {
		handle: ".column-drag-handler",
		ghostClass: "sortable-ghost",
		setData: function (event) {
			event.setData("Text", "");
		},
		onStart: event => {
			tableColumnRows.value = treeColumnsToArray();
		},
		onMove: ({
			dragged: draggedElement,
			related: targetElement
		}) => {
		const draggedRow = tableColumnRows.value[draggedElement.rowIndex];
		const targetRow = tableColumnRows.value[targetElement.rowIndex];

		if (draggedRow.nodeLevel !== targetRow.nodeLevel) {
			console.error('只能在同级节点之间进行拖拽排序！');
			return false;
		}
		},
		onEnd: event => {
			const movedRow = tableColumnRows.value[event.oldIndex];
			const targetRow = tableColumnRows.value[event.newIndex];

			if (movedRow.nodeLevel !== targetRow.nodeLevel || event.oldIndex === event.newIndex) return;

			const movedColumnId = movedRow.columnId;
			const targetColumnId = targetRow.columnId;

			let parentArray = getParentArrayOfTableColumn(localTableColumns.value, movedColumnId);
			let movedIndex = parentArray.findIndex(item => item.columnId === movedColumnId);
			let targetIndex = parentArray.findIndex(item => item.columnId === targetColumnId);
			//console.log('movedColumnId', movedColumnId,'targetColumnId',targetIndex)
			if (movedIndex > targetIndex) {
				parentArray.splice(targetIndex, 0, deepClone(parentArray[movedIndex]));
				parentArray.splice(movedIndex + 1, 1);
			} else {
				parentArray.splice(targetIndex + 1, 0, deepClone(parentArray[movedIndex]));
				parentArray.splice(movedIndex, 1);
			}
			//updateTableColumns();	
		}
	})				
};

const showRenderDialog=(tableColumn) =>{
		currentTableColumn.value = tableColumn
		formatterCode.value = tableColumn.formatterFn || 'return cellValue;'
		showRenderDialogFlag.value = true
	}

const saveColumnRender = () => {
	if (currentTableColumn.value) {
		currentTableColumn.value['formatterFn'] = formatterCode.value
	}
	showRenderDialogFlag.value = false		
	//console.log('saveColumnRender', props.columns)
	//emit('update:localTableColumns', [...props.columns]) // 可选：通知父组件更新
}
const showFieldOptionsDialog=(tableColumn) =>{
	currentTableColumn.value = tableColumn
	fieldOptions.value.type = tableColumn.fieldOptions.type || 'select'
	fieldOptions.value.format = tableColumn.fieldOptions.format || ''
	fieldOptions.value.options = tableColumn.fieldOptions.options || [{ value: '1', label: '选项1' },{ value: '2', label: '选项2' }]
	showFieldOptionsDialogFlag.value = true
}

const saveFieldOptions = () => {
	if (currentTableColumn.value) {
		currentTableColumn.value.fieldOptions.type = fieldOptions.value.type
		currentTableColumn.value.fieldOptions.format = fieldOptions.value.format
		currentTableColumn.value.fieldOptions.options = fieldOptions.value.options
	}
	showFieldOptionsDialogFlag.value = false
}
const showSQLToColumnsDialog =()=>{
	sqlString.value=""
	showSQLToColumnDialogFlag.value = true
}

const saveSQLToColumns = () => {
	if (sqlString.value) {
		const result = processSqlAndGenerateTestData(sqlString.value)
		//console.log('result',result)
		localTableColumns.value = [...result.columns]
		localTableData.value = [...result.data]		
	}
	showSQLToColumnDialogFlag.value = false
}

const expandAllTableColumns = (columns) => {
	columns.forEach(column => {
		singleTable.value.toggleRowExpansion(column, true);
		if (column.children) {
			expandAllTableColumns(column.children);
		}
	});
}

const handleExportToJson = () => { 
	exportToJson(getTableColumnsAndData())
}

const handleImportFromJson = async () => { 
	const jsonData = await importFromJson()
	if(jsonData){
		setTableColumns(jsonData.tableColumns || jsonData)
		//setTableData(jsonData.tableData || [])
	}		
}

const getTableColumnsAndData = () => { 
	return {tableColumns:deepClone(getTableColumns()),tableData:deepClone(getTableData())}
}

onMounted(async () =>{
	//console.log(props.columns)
	await nextTick(()=>{
		dragSort()
		expandAllTableColumns(localTableColumns.value)
	})
})
watch(
	() => props.tableColumns,(newVal) => {
		localTableColumns.value = newVal
	},{ deep: true, immediate: true }
)
watch(
	() => props.tableData,(newVal) => {
		localTableData.value = newVal
	},{ deep: true, immediate: true }
)

watch(localTableColumns, (val) => {
  emit('update:tableColumns', val)
})

watch(localTableData, (val) => {
  emit('update:tableData', val)
})

const setTableColumns = (columns) => {
  localTableColumns.value = columns
}
const setTableData = (data) => {
  localTableData.value = data
}

const getTableColumns = () => {
  return localTableColumns.value
}
const getTableData = () => {
  return localTableData.value
}
//暴露方法可进行手动同步或调用
defineExpose({
	setTableColumns,
	setTableData,
	getTableColumns,
	getTableData,
})
		
</script>

<style scoped>
.drag-sort-col {
		padding-top: 8px;
		cursor: move;
	}
.dialog-footer{
	text-align: right;
}
.opt-btn-menu{
	.el-menu-item{
		height: 32px !important;
	}
}
</style>